package com.tvb.comm.security;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.AntPathRequestMatcher;
import org.springframework.security.web.util.RequestMatcher;

import com.tvb.pojo.LoginRole;
import com.tvb.service.UserRoleService;

/**
 * @author stan
 *
 */
//1 加载资源与权限的对应关系
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
	static Log log = LogFactory.getLog(MySecurityMetadataSource.class.getName());
	
	private static final String LOGIN_USER_ROLE_VIEWS_KEY = "loginUserRoleViewS@csao3"; 
	@Autowired
	private UserRoleService userRoleService;
	//由spring调用
	public MySecurityMetadataSource() {
		//loadResourceDefine();
	}

	private static Map<String, List<ConfigAttribute>> resourceMap = null;

	public Collection<ConfigAttribute> getAllConfigAttributes() {
		// TODO Auto-generated method stub
		return null;
	}

	public boolean supports(Class<?> clazz) {
		// TODO Auto-generated method stub
		return true;
	}
	//加载所有资源与权限的关系
	private void loadResourceDefine() {
		if(resourceMap == null) {
			try {
				resourceMap = new HashMap<String, List<ConfigAttribute>>();
				List<LoginRole> roles = userRoleService.findAllRoleViews();
				for (LoginRole loginRole : roles) {
					List<ConfigAttribute> role = new ArrayList<ConfigAttribute>();
					ConfigAttribute configAttribute = new SecurityConfig(String.valueOf(loginRole.getRoleCode()));
					role.add(configAttribute);
					for (String url : loginRole.getPurviews()) {
						resourceMap.put(url, role);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
				throw new AccessDeniedException("系统异常");
			}
			
		}
/*		
		Set<Entry<String, Collection<ConfigAttribute>>> resourceSet = resourceMap.entrySet();
		Iterator<Entry<String, Collection<ConfigAttribute>>> iterator = resourceSet.iterator();*/
	}
	//返回所请求资源所需要的权限
	public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
		if(resourceMap == null || resourceMap.size()==0) {
			loadResourceDefine();
		}
		SecurityContext seContext = SecurityContextHolder.getContext();
		FilterInvocation invocation = (FilterInvocation) object;
		HttpServletRequest request = invocation.getRequest();
		String requestUrl = invocation.getRequestUrl();
		int firstQuestionMarkIndex = requestUrl.indexOf("?");
        if (firstQuestionMarkIndex != -1) {
        	requestUrl = requestUrl.substring(0, firstQuestionMarkIndex);
        }
		Authentication auth = seContext.getAuthentication();
		Object obj = auth.getPrincipal();
		log.info("requestUrl is " + requestUrl);
		if(obj instanceof UserDetails){
			UserDetails user  = (UserDetails)obj;
			log.info("登录人: " + user.getUsername());
			
			Iterator<GrantedAuthority> cad = (Iterator<GrantedAuthority>) user.getAuthorities().iterator();
			Iterator<Map.Entry<String,List<ConfigAttribute>>> roleViews= resourceMap.entrySet().iterator();
			
			Set<String> userURLs = findUserRoleViews(request, cad, roleViews);
			
			//获取登录人所有能够访问url
	        Iterator<String> ite = userURLs.iterator();//得到资源
			while (ite.hasNext()) {
				String resURL = ite.next();
				RequestMatcher urlMatcher = new AntPathRequestMatcher(resURL);
				if (urlMatcher.matches(request)) {
					return resourceMap.get(resURL);
				}
			}
		}else{
			log.info("未登录");
			try {
				invocation.getHttpResponse().sendRedirect(request.getContextPath()+"/login.jsp");
			} catch (IOException e) {
				e.printStackTrace();
			}
			return null;
		}
		return null;
	}

	/**
	 * 收集用户能够访问的资源地址
	 * @param request
	 * @param authority 用户的权限列表
	 * @param roleViews 所有的资源列表
	 * @return
	 */
	private Set<String> findUserRoleViews(HttpServletRequest request,
			Iterator<GrantedAuthority> authority,
			Iterator<Map.Entry<String, List<ConfigAttribute>>> roleViews) {
		Set<String> userURLs = null;
		Object userURLs_obj = request.getSession().getAttribute(
				LOGIN_USER_ROLE_VIEWS_KEY);
		if (userURLs_obj != null)
			userURLs = (Set<String>) userURLs_obj;
		else
			userURLs = new HashSet<String>();
		// 根据用户权限收集用户可以访问的资源
		if (userURLs_obj == null) {
			while (authority.hasNext()) {
				// 用户的权限
				String userAuthority = authority.next().getAuthority();
				log.info("登录人的GrantedAuthority: " + userAuthority);
				/* 遍历所有权限资源 */
				while (roleViews.hasNext()) {
					Map.Entry<String, List<ConfigAttribute>> roleView = roleViews
							.next();
					// 匹配权限
					for (ConfigAttribute attribute : roleView.getValue()) {
						if (userAuthority.equals(attribute.getAttribute())) {
							userURLs.add(roleView.getKey());
						}
					}
				}
			}
			request.getSession().setAttribute(LOGIN_USER_ROLE_VIEWS_KEY,
					userURLs);
		}
		return userURLs;
	}
	
	
}
